/*
 * Copyright (C) 2008, Velocityme Partnership
 * SprintActions.java
 *
 * Created on 28 August 2008, 20:40
 */

package com.velocityme.www.interfaces.nodeactions;

import com.velocityme.entity.Activity;
import com.velocityme.entity.Person;
import com.velocityme.entity.Sprint;
import com.velocityme.session.KeyLocal;
import com.velocityme.session.NodeLocal;
import com.velocityme.session.SprintLocal;
import com.velocityme.utility.DurationRemaining;
import com.velocityme.utility.TimeSummaryTable;
import com.velocityme.www.actionforms.nodeactionforms.SprintActionForm;
import com.velocityme.www.dto.IdName;
import com.velocityme.www.dto.PersonTimeDTO;
import com.velocityme.www.dto.ProgressDTO;
import com.velocityme.www.dto.TimeReportDTO;
import com.velocityme.www.interfaces.ShowNodeAction;
import com.velocityme.www.utility.NodeUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;


/**
 *
 * @author  Robert
 */
public class SprintActions extends NodeActions {

    /** Creates a new instance of SprintActions */
    public SprintActions() {
    }

    @Override
    public ActionForward show(ActionMapping mapping,
                              ActionForm form,
                              HttpServletRequest request,
                              HttpServletResponse response) throws Exception {
        Long nodeId = (Long)request.getAttribute("nodeId");
        HttpSession session = request.getSession();
        KeyLocal key = (KeyLocal)session.getAttribute("sessionKey");
        Sprint sprint = lookupSprintBean().findSprint(key, nodeId);
        session.setAttribute("sprint", sprint);
        Collection progressDTOs = calculateProgressDTOs(lookupSprintBean().searchProgressSum(key, sprint));
        session.setAttribute("progressValue", progressDTOs);
        session.setAttribute("total", calculateMax(progressDTOs));
        return mapping.findForward("ACTION_DISPLAY");
    }

    @Override
    public ActionForward showCreate(ActionMapping mapping,
                                    ActionForm form,
                                    HttpServletRequest request,
                                    HttpServletResponse response) throws Exception {
        Long nodeId = (Long)request.getAttribute("nodeId");
        HttpSession session = request.getSession();
        KeyLocal key = (KeyLocal)session.getAttribute("sessionKey");
        session.setAttribute("allPersonPairs", NodeUtil.getAllPersonPairs(key));
        session.setAttribute("teamPersonPairs", new ArrayList<IdName>());
        SprintActionForm sprintAF = new SprintActionForm();
        sprintAF.setScrumMasterId(key.getPerson().getId());
        Date now = new Date();
        sprintAF.setStartDate(now);
        sprintAF.setStopDate(now);
        session.setAttribute("sprintAF", sprintAF);
        session.setAttribute("years", NodeUtil.getInstance().getYears());
        session.setAttribute("months", NodeUtil.getInstance().getMonths());
        session.setAttribute("days", NodeUtil.getInstance().getDays());
        Sprint sprint = new Sprint();
        sprint.setParentNode(lookupNodeBean().findNode(key, nodeId));
        session.setAttribute("sprint", sprint);
        return mapping.findForward("ACTION_EDIT");
    }

    @Override
    public ActionForward showEdit(ActionMapping mapping,
                                  ActionForm form,
                                  HttpServletRequest request,
                                  HttpServletResponse response) throws Exception {
        Long nodeId = (Long)request.getAttribute("nodeId");
        HttpSession session = request.getSession();
        KeyLocal key = (KeyLocal)session.getAttribute("sessionKey");
        Sprint sprint = lookupSprintBean().findSprint(key, nodeId);
        session.setAttribute("sprint", sprint);
        SprintActionForm sprintAF = new SprintActionForm();
        sprintAF.setScrumMasterId(sprint.getScrumMaster().getId());
        Collection<IdName> teamPersonPairs = new ArrayList<IdName>();
        for (Person person: sprint.getTeamMembers()) {
            teamPersonPairs.add(new IdName(person.getId(), person.toString()));
        }
        sprintAF.setStartDate(sprint.getStartDate());
        sprintAF.setStopDate(sprint.getStopDate());
        session.setAttribute("teamPersonPairs", teamPersonPairs);
        session.setAttribute("sprintAF", sprintAF);
        session.setAttribute("years", NodeUtil.getInstance().getYears());
        session.setAttribute("months", NodeUtil.getInstance().getMonths());
        session.setAttribute("days", NodeUtil.getInstance().getDays());
        session.setAttribute("allPersonPairs", NodeUtil.getAllPersonPairs(key));
        return mapping.findForward("ACTION_EDIT");
    }

    @Override
    public ActionForward edit(ActionMapping mapping,
                              ActionForm form,
                              HttpServletRequest request,
                              HttpServletResponse response) throws Exception {
        HttpSession session = request.getSession();
        KeyLocal key = (KeyLocal)session.getAttribute("sessionKey");
        Long nodeId;
        if (request.getParameter("btnSubmit").equals("OK")) {
            Sprint sprint = (Sprint)session.getAttribute("sprint");
            ((SprintActionForm)form).extractSprint(key, sprint);
            if (sprint.getId() != null) {
                lookupSprintBean().editSprint(key, sprint);
            }
            else {
                sprint = lookupSprintBean().createSprint(key, sprint);
            }
            nodeId = sprint.getId();
        }
        // Cancel simply displays the original node again
        else {
            nodeId = (Long)session.getAttribute("nodeId");
        }
        request.setAttribute("nodeId", nodeId);
        return mapping.findForward("ACTION_SUCCESS");
    }

    public ActionForward showBurnDown(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        Long nodeId = (Long) request.getAttribute("nodeId");
        HttpSession session = request.getSession();
        KeyLocal key = (KeyLocal) session.getAttribute("sessionKey");
        Sprint sprint = lookupSprintBean().findSprint(key, nodeId);
        ShowNodeAction.setupTreeDisplay(session, sprint, "BurnDown");
        Map<String,DurationRemaining> durations = lookupSprintBean().searchDurationSum(key, sprint);
        Collection burnDownDTOs = TaskActions.calculateBurnDownDTOs(durations);
        session.setAttribute("burnDownValue", burnDownDTOs);
        session.setAttribute("total", TaskActions.calculateMax(burnDownDTOs));
        return mapping.findForward("ACTION_DISPLAY");
    }

    private ActionForward showTimeReportTemplate(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response, String tab)
            throws Exception {
        Long nodeId = (Long) request.getAttribute("nodeId");
        HttpSession session = request.getSession();
        KeyLocal key = (KeyLocal) session.getAttribute("sessionKey");
        Sprint sprint = lookupSprintBean().findSprint(key, nodeId);
        ShowNodeAction.setupTreeDisplay(session, sprint, tab);
        Map<String,Object> results;
        if (tab.equals("Time Report"))
            results = lookupSprintBean().getSearchTimeLog(key, sprint);
        else
            results = lookupSprintBean().getUnplannedSearchTimeLog(key, sprint);
        TimeReportDTO timeReportDTO = new TimeReportDTO("/",
                                                        sprint.getStartDate(),
                                                        sprint.getStopDate(),
                                                        new Date(),
                                                        (Collection)results.get("Entries"),
                                                        (Collection)results.get("Names"),
                                                        (Collection)results.get("Summaries"));
        session.setAttribute("timeReportDTO", timeReportDTO);
        Iterator i = ((Collection)results.get("Names")).iterator();
        TimeSummaryTable t = (TimeSummaryTable)((List)results.get("Summaries")).get(0);
        List<PersonTimeDTO> personTimeDTO = new ArrayList<PersonTimeDTO>();
        if (t.getRows().size() > 0) {
            TimeSummaryTable.Row row = (TimeSummaryTable.Row)(((List)t.getRows()).get(0));
            for (int j = 0; j < row.getLongPercents().length - 1; j++) {
                String name = (String)i.next();
                long duration = row.getLongPercents()[j].getLong();
                int percent = (int)(duration * 100L / t.getMax());
                personTimeDTO.add(new PersonTimeDTO(duration, name, percent));
            }
        }
        session.setAttribute("personTimeDTO", personTimeDTO);
        return mapping.findForward("ACTION_DISPLAY");
    }

    public ActionForward showTimeReport(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        return showTimeReportTemplate(mapping, form, request, response, "Time Report");
    }

    public ActionForward showUnplannedReport(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        return showTimeReportTemplate(mapping, form, request, response, "Unplanned");
    }

    static public Collection<ProgressDTO> calculateProgressDTOs(Map<Activity,DurationRemaining> progress) {
        Collection<ProgressDTO> progressDTOs = new ArrayList<ProgressDTO>();
        for (Map.Entry<Activity,DurationRemaining> entry: progress.entrySet()) {
            Activity activity = entry.getKey();
            DurationRemaining dr = entry.getValue();
            progressDTOs.add(new ProgressDTO(activity.getProjectPathName(), activity, dr.getDuration_min(), dr.getRemaining_min()));
        }
        return progressDTOs;
    }

    static public Integer calculateMax(Collection<ProgressDTO> progressDTOs) {
        Iterator i = progressDTOs.iterator();
        int total = 0;
        for (ProgressDTO bd: progressDTOs) {
            total = Math.max(total, bd.getDuration_min() + bd.getRemaining_min());
        }
        return total;
    }

    private SprintLocal lookupSprintBean() {
        try {
            Context c = new InitialContext();
            return (SprintLocal) c.lookup("java:comp/env/SprintBean");
        } catch (NamingException ne) {
            Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", ne);
            throw new RuntimeException(ne);
        }
    }

    private NodeLocal lookupNodeBean() {
        try {
            Context c = new InitialContext();
            return (NodeLocal) c.lookup("java:comp/env/NodeBean");
        } catch (NamingException ne) {
            Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", ne);
            throw new RuntimeException(ne);
        }
    }

}
